#pragma once

#include "qfile.h"

using namespace micro::utils;


namespace micro
{
namespace files
{

class QArchive
{
public:
    // Flag values
    enum Mode { load = 0, store = 1, bNoFlushOnDelete = 2, bNoByteSwap = 4 };
    
    enum SchemaMapReservedRefs { objTypeArrayRef = 1 };
    enum LoadArrayObjType { typeUndefined = 0, typeCRuntimeClass = 1, typeCObject = 2 };
    
    
private:
    QFile*	m_pFile;
    Mode	m_modeArchive;
    
    //for advanced use
    UINT	m_nObjectSchema;
    QString m_strFileName;
    
protected:
    // archive objects cannot be copied or assigned
    QArchive( const QArchive& arSrc ) {}
    void operator=( const QArchive& arSrc ) {}
    
    
    
    
    bool m_bUserBuf;
    int m_nBufSize;
    
    
    
    BYTE* m_lpBufCur;
    BYTE* m_lpBufMax;
    BYTE* m_lpBufStart;
    
    
    // advanced parameters (controls performance with large archives)
    UINT m_nGrowSize;
    UINT m_nHashSize;
    
    
    
public:

    QArchive( QFile* pFile, Mode mode = load, int nBufSize = 4096, BYTE* lpBuf = nullptr );
    ~QArchive();
    
// Attributes



    bool	IsLoading()		const
    {
        return   m_modeArchive == load;
    }
    bool	IsStoring()		const
    {
        return  m_modeArchive == store;
    }
    bool	IsByteSwapping() const
    {
        return false;
    }
    bool	IsBufferEmpty()	const
    {
        return m_lpBufCur == m_lpBufMax;
    }


//////////////////////////////////////////////////////////////////////////

    void	SetObjectSchema( UINT nSchema )
    {
        m_nObjectSchema = nSchema;
    }
    UINT GetObjectSchema()  // only valid when reading a QObject*
    {
        return m_nObjectSchema;
    }
	// advanced operations (used when storing/loading many objects)
	void SetStoreParams( UINT nHashSize = 2053, UINT nBlockSize = 128 );
	void SetLoadParams( UINT nGrowBy = 1024 );
    
    


// Operations
    size_t Read( void* lpBuf, size_t nMax );
    
    void EnsureRead( void* lpBuf, UINT nCount );
    void Write( const void* lpBuf, UINT nMax );
    void Flush();
    void Close();
    void Abort();   // close and shutdown without exceptions
    
    // reading and writing strings
    void	WriteString( LPCTSTR lpsz );
    LPTSTR	ReadString( LPTSTR lpsz, UINT nMax );
    bool	ReadString( QString& rString );
    
    // special functions for reading and writing (16-bit compatible) counts
    DWORD	ReadCount();
    void	WriteCount( DWORD dwCount );
    
public:
    // Object I/O is pointer based to avoid added construction overhead.
    // Use the Serialize member function directly for embedded objects.
    
    
    //friend QArchive&  operator<<(QArchive& ar, const QObject* pOb);
    
    //friend QArchive&  operator>>(QArchive& ar, QObject*& pOb);
    //friend QArchive&  operator>>(QArchive& ar, const QObject*& pOb);
    
    
    
    // insertion operations
    QArchive& operator<<( BYTE by );
    QArchive& operator<<( WORD w );
    QArchive& operator<<( LONG l );
    QArchive& operator<<( DWORD dw );
    QArchive& operator<<( float f );
    QArchive& operator<<( double d );
    QArchive& operator<<( LONGLONG dwdw );
    QArchive& operator<<( ULONGLONG dwdw );
    
    QArchive& operator<<( int i );
    QArchive& operator<<( short w );
    QArchive& operator<<( char ch );
    QArchive& operator<<( wchar_t ch );
    
    
    QArchive& operator<<( unsigned int );
    QArchive& operator<<( bool b );
    QArchive& operator<<(const QString& str );
    
    
    
    
    // extraction operations
    QArchive& operator>>( BYTE& by );
    QArchive& operator>>( WORD& w );
    QArchive& operator>>( DWORD& dw );
    QArchive& operator>>( LONG& l );
    QArchive& operator>>( float& f );
    QArchive& operator>>( double& d );
    QArchive& operator>>( LONGLONG& dwdw );
    QArchive& operator>>( ULONGLONG& dwdw );
    
    QArchive& operator>>( int& i );
    QArchive& operator>>( short& w );
    QArchive& operator>>( char& ch );
    QArchive& operator>>( wchar_t& ch );
    
    
    QArchive& operator>>( unsigned int& u );
    QArchive& operator>>( bool& b );
    QArchive& operator>>( QString& str );
    
    
    // object read/write
    //QObject* ReadObject(const CRuntimeClass* pClass);
    
    //void WriteObject(const QObject* pOb);
    // advanced object mapping (used for forced references)
    //void MapObject(const QObject* pOb);
    
    
   
    
    //void EnsureSchemaMapExists(CArray<LoadArrayObjType, const LoadArrayObjType&>** ppObjTypeArray = nullptr);
// Implementation
public:
    bool m_bForceFlat;  // for COleClientItem implementation (default TRUE)
  
    void FillBuffer( UINT nBytesNeeded );
    void CheckCount();  // throw exception if m_nMapCount is too large
    
    
    
    
};

//serializable object must implement this interface
//class IQSerializable
//{
//public:
//    virtual void Serialize( QArchive& ar ) = 0;
//};



}


}//micro

